/** 
 * 游戏界面层
 * Author      : donggang
 * Create Time : 2016.9.24
 */
game.UILayer = module.exports = cc.Class({
    extends : cc.Node,

    ctor : function () {
        this.name = game.SceneLayerType.UI;

        this._nodes    = {};                           // 节点结合
        this._handlers = {};                           // 处理流程状态

        // 设置背景水平居中、垂直居低
        this.setContentSize(cc.director.getWinSize().width, cc.director.getWinSize().height);
        
        // 子节点移除事件
        this.on("child-removed", this._onChildRemoved, this);
    },

    /** 子节点从父节点移除事件 */
    _onChildRemoved : function(event) {
        // var parentNode = event.currentTarget;
        // var childNode  = event.detail;
        // var operate    = childNode.manager_data;
    },

    /** 节点显示之前 */
    _showBefore   : function(node) {},

    /** 显示新节点 */
    _show : function(node, operate, completeCallback){
        // 显示之前
        this._showBefore(node);                          

        // 绑定场景管理相关当前节点数据
        node.manager_data = operate;
        
        // 节点添加到场景上
        if (node.parent == null){
            this.addChild(node, this.childrenCount);
        }
        
        // 子节点添加到父节点事件
        node.applyComponentsFunction("onAdded", operate.addedToSceneParams);
        
        // 添加到场景事件
        if (operate.addedToScene) operate.addedToScene(node);

        // 加载流程结束状态终止
        if (this._handlers[operate.resPath]) {
            this._handlers[operate.resPath].end();   
            delete this._handlers[operate.resPath];
        }
        
        // 新场景处理完成事件
        if (completeCallback) completeCallback(node);      
    },

    /** 
     * 节点是否存在 
     * @param path(string)                             资源路径
     */
    isExist : function(path){
        if (this._nodes[path])
            return true;
        return false;
    },

    /** 
     * 添加预制实例
     * @param resPath      : "common/prefab"                      预制资源路径
     * @param operate{
     *      preloaded      : "common/image"|['a.png', 'b.png']    预加载文件夹
     *      handler        : function                             预加回调方法
     *      params         : [a,b,c]                              自定义参数，在新界面的added事件中接受
     *      animationOpen  : path(string),clip(string)            新场景打开动画（两个动画必须同时存在）
     *      animationClose : path(string),clip(string)            旧场景关闭动画（两个动画必须同时存在）
     *      addedToScene   : function                             添加到场景事件
     *      removedToScene : function                             移除场景事件
     * }
     * completeCallback : function(node)                          加载完成回调（内部使用）
     */
    add : function(resPath, operate, completeCallback){
        if (operate != null && typeof operate != "object") { 
            cc.error("【场景】参数 operate 必须是一个 object 对象");
            return;
        }
        else if (operate == null) operate = {};
        
        // 添加到场景时的参数
        operate.addedToSceneParams = operate.params;
        delete operate["params"];

        // 新场景预制资源路径
        operate.resPath = resPath;

        var newNode = this._nodes[operate.resPath];
        if (newNode != null && newNode.parent != null) {
            cc.warn("【场景】{0} 层的 {1} 资源已在舞台上".format(this.name, operate.resPath));
            return;
        }
        else if(newNode != null && newNode.parent == null) {
            this._show(newNode, operate, completeCallback); 
        }
        else if (this._handlers[operate.resPath] == null) {
            this._handlers[operate.resPath] = new game.UiLayerHandler();                    // 状态机队列
            this._handlers[operate.resPath].start(this, operate, completeCallback);
        }
    },

    /** 
     * 添加预制实例
     * @param resPathOrCCNode(string|cc.Node)   资源路径
     * @param cleanup(boolen)                   是否释放对象资源
     */
    remove : function(resPathOrCCNode, cleanup) {
        var resPath;
        if (resPathOrCCNode instanceof cc.Node) {
            if (resPathOrCCNode.manager_data == null) {
                cc.warn("【场景】节点不在框架管理范围内");
                return;
            }

            resPath = resPathOrCCNode.manager_data.resPath;
        }
        else {
            resPath = resPathOrCCNode;
        }
        
        var node = this._nodes[resPath];                    // 获取当前删除的节点窗口
        if (node == null){
            cc.warn("【场景】名为 {0} 的界面不存在".format(resPath));
            return;
        } 

        var operate = node.manager_data;                    // 获取节点自己的管理数据

        // 从父节点移除节点
        node.parent = null;

        node.applyComponentsFunction("onRemoved");

        // 触发从场景移除事件
        if (operate.removedToScene) operate.removedToScene(); 

        // 释放窗口节点
        if (cleanup != null && cleanup == true) { 
            delete this._nodes[resPath];
            node.dispose();

            cc.log("【场景】释放了名为 {0} 的界面".format(resPath));

            if (game.MemoryConfig.removeNode)
                cc.textureCache.memory(); 
        }
    },

    /** 
     * 清除逻辑层节点 
     * @param cleanup(boolen)                   是否清理在实例管理器中的缓存
     */
    clear : function(cleanup = false){
        if (cleanup){
            this._nodes = {};
        }
        this.removeAllChildren(cleanup);
    }
});
